import { Tasks } from "@/global/creep-task";
import { runIntervally } from "@/utils/functions/inInterval";
import { NormalColony } from "../../NormalColony";
import { BaseColonyModule } from "../moduleBase";

const cache: Record<string, Id<ConstructionSite>[]> = {};

// 配置项 ===================================================
const DOWNGRADE_DEADLINE = 3000;
const WORKER_FORTIFY_LIMIT = 10000;
// =========================================================

const reloadSiteOf = (colony: NormalColony) => {
    let sites: Id<ConstructionSite>[] = [];
    [colony.capital, ...colony.outposts].forEach(room => {
        const s = room.find(FIND_MY_CONSTRUCTION_SITES);
        sites.push(...s.map(site => site.id));
    });
    // some tricky nullish problems here
    cache[colony.name] = sites.filter(Boolean).sort(siteCompareFnWithId);
}

const siteCompareFnWithId = (id0: Id<ConstructionSite>, id1: Id<ConstructionSite>) => {
    const a = Game.getObjectById(id0), b = Game.getObjectById(id1);
    // 比较建筑类型和优先级
    const priority = {
        [STRUCTURE_SPAWN]: 0,
        [STRUCTURE_TOWER]: 1,
        [STRUCTURE_EXTENSION]: 2,
        [STRUCTURE_STORAGE]: 3,
        [STRUCTURE_TERMINAL]: 4,
        [STRUCTURE_CONTAINER]: 5,
        [STRUCTURE_LINK]: 6,
        [STRUCTURE_EXTRACTOR]: 7,
        [STRUCTURE_LAB]: 8,
        [STRUCTURE_NUKER]: 9,
        [STRUCTURE_OBSERVER]: 10,
        [STRUCTURE_POWER_SPAWN]: 11,
        [STRUCTURE_WALL]: 12,
        [STRUCTURE_RAMPART]: 13,
        [STRUCTURE_ROAD]: 14
    };
    // note! 如果建筑不在这个表里面，由于 undefined-undefined = NaN，会自动到排序到最后一项
    return priority[a?.structureType] - priority[b?.structureType];
}

export class WorkModule extends BaseColonyModule {

    collectEnergy(worker: Creep) {
        const colony = worker.getHomeColony() as NormalColony;
        let struct: AnyStoreStructure[] = [];
        if (colony.level <= 3) {
            struct = [
                ...colony.structMgr.getHatcheryBatteries(),
                colony.structMgr.getSpawn(0)
            ];
        }
        else {
            struct = [
                // 从 storage 和 terminal 中拿
                colony.capital.getStorage(),
                colony.capital.getTerminal(),
                ...colony.structMgr.getHatcheryBatteries()
            ];
        }
        if (worker.collectEnergy(...struct) === false) {
            worker.say(':(', true);
        }
    }

    assignWork(worker: Creep) {
        // 如果控制器即将降级，就优先升级控制器
        const colony = worker.getHomeColony() as NormalColony;
        if (colony.capital.getController().ticksToDowngrade <= DOWNGRADE_DEADLINE) {
            worker.addTask(Tasks.upgrade(colony.capital.getController()));
            return true;
        }
        // 没有 commonTower 前要修 container
        if (!colony.structMgr.getCommonTower()) {
            const containers = colony.capital.getContainers();
            const breakingContainer = containers.find(c => c.hits <= c.hitsMax * 0.9);
            if (breakingContainer) {
                worker.addTask(Tasks.repair(breakingContainer));
                return true;
            }
        }
        // 建造工地
        const availableSiteId = (cache[colony.name] ?? []).find(id =>
            Game.getObjectById(id).targetedBy.length <= 3   // 避免过于拥挤
        );
        const site = Game.getObjectById(availableSiteId);
        if (site) {
            worker.addTask(Tasks.build(site));
            return true;
        }
        // 辅助刷墙
        const barriers = colony.capital.getBarriers();
        const breakingBarrier = barriers.find(barrier =>
            barrier.hits <= WORKER_FORTIFY_LIMIT && barrier.targetedBy.length < 1
        );
        if (breakingBarrier) {
            worker.addTask(Tasks.fortify(breakingBarrier));
            return true;
        }
        // 默认升级控制器
        if (colony.level < 8) {
            worker.addTask(Tasks.upgrade(colony.capital.getController()));
            return true;
        }
        // 没活干，暂停 10 ticks 节省 CPU
        worker.makeSuspend(10);
        return false;
    }

    handle() {
        // 初始化或刷新工地
        if (cache[this.colony.name] === undefined) {
            reloadSiteOf(this.colony);
        }
        runIntervally(IntervalLength.short, () => reloadSiteOf(this.colony));
        const constructionSites = cache[this.colony.name];
        // 分配活干
        this.runCreeps(CreepRole.worker, worker => {
            // 有能量，分配工作任务，否则拿能量
            if (worker.store[RESOURCE_ENERGY] > 0) {
                this.assignWork(worker);
            }
            else {
                this.collectEnergy(worker);
            }
        });
    }

}